package app.gui;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;

import app.Main;
import app.conn.WebDB;

public class ConfigModel {

	public static final String VENT = "V";
	public static final String WAT = "W";
	public static final String DEL = "D";

	public static final String WAT_DELAY_UNITS = "min";
	public static final String VENT_DELAY_UNITS = "min";
	
	public static final int WAT_DELAY_STEP = 1;
	public static final int VENT_DELAY_STEP = 5;


	private boolean remoteAccess;
	private String unitId;

	/*
	 * Store time data
	 *          row col: 0-time 1-delay
	 *			 v   v
	 *   byte	[ ]	[ ] 
	 */
	private int[][] ventilationData;
	private int[][] wateringData;

	private boolean autoVentilation;
	private boolean autoWatering;
	private int minTemp;
	private int maxTemp;
	private int minHum;
	private int maxHum;
	private int minSM;
	private int maxSM;


	private int recDelay;
	private int manDelay;

	/*
	 * Constructors
	 */
	public ConfigModel() {
	}

	public ConfigModel(String[] data) {
		parseData(data);
	}

	public void save() {
		String[] data = getData();
		if(isRemoteAccess()) {
			try {
				WebDB.clearConfig(unitId);
				for(String line : data) {
					WebDB.sendConfig(unitId, line);
				}
				WebDB.setUpdateConfig(unitId);
			} catch (IOException e) {
				Main.showError("Chyba připojení", "Nelze odeslat nastavení");
				return;
			}
		}
		else {
			if(MainFrame.getInstance().cnfFile != null) {
				try {
					PrintWriter writer = new PrintWriter(MainFrame.getInstance().cnfFile);
					for(String line : data) {
						writer.println(line);
					}
					writer.close();
				} catch (FileNotFoundException e) {
					Main.showError("Chyba souboru", "Nelze uložit data do souboru");
					return;
				}
			}
			else {
				Main.showError("Chyba souboru", "Nelze uložit data do souboru");
				return;
			}
		}
	}

	public void parseData(String[] data) {
		if(data == null)
			return;

		LinkedList<int[]> ventData = new LinkedList<int[]>();
		LinkedList<int[]> watData = new LinkedList<int[]>();
		int number = 0;
		String[] splited;

		try {
			for(String s : data) {
				splited = s.split(" ");
				number = Integer.parseInt(splited[1]);
				int[] entry = new int[2];
				// Ventilation data
				if(splited[0].equals(VENT)) {
					if(number < 65) {
						entry[0] = Integer.parseInt(splited[2]);
						entry[1] = Integer.parseInt(splited[3]);
						ventData.add(entry);
					}
					else {
						switch(number) {
						case 100 :
							setAutoVentilation(true);
							setMinTemp(Integer.parseInt(splited[2]));
							setMaxTemp(Integer.parseInt(splited[3]));
							break;

						case 101 :
							setAutoVentilation(true);
							setMinHum(Integer.parseInt(splited[2]));
							setMaxHum(Integer.parseInt(splited[3]));
							break;
						}
					}
				}
				// Watering data
				else if(splited[0].equals(WAT)) {
					if(number < 65) {
						entry[0] = Integer.parseInt(splited[2]);
						entry[1] = Integer.parseInt(splited[3]);
						watData.add(entry);
					}
					else {
						switch(number) {
						case 100 :
							setAutoWatering(true);
							setMinSM(Integer.parseInt(splited[2]));
							setMaxSM(Integer.parseInt(splited[3]));
							break;
						}				
					}
				}
				// Delay data
				else if(splited[0].equals(DEL)) {
					switch(number) {
					case 1 :
						setRecDelay(Integer.parseInt(splited[2]));
						break;
					case 2 :
						setManDelay(Integer.parseInt(splited[2]));
						break;
					}
				}
			}
			int[][] vData = new int[ventData.size()][2];
			for(int i = 0; i < ventData.size(); i++) {
				vData[i][0] = ventData.get(i)[0];
				vData[i][1] = ventData.get(i)[1];
			}
			setVentilationData(vData);

			int[][] wData = new int[watData.size()][2];
			for(int i = 0; i < watData.size(); i++) {
				wData[i][0] = watData.get(i)[0];
				wData[i][1] = watData.get(i)[1];
			}
			setWateringData(wData);
		} catch (Exception e) {
			Main.showError("Chyba", e.toString());
		}
	}

	public String[] getData() {
		boolean vent = (ventilationData != null);
		boolean wat = (wateringData != null);
		int length = (vent ? ventilationData.length : 0) + (wat ? wateringData.length : 0) +
				(autoWatering ? 1 : 0) + (autoVentilation ? 2 : 0) + 2;
		String[] data = new String[length];
		// add ventilation times
		int p = 0;

		for(int i = 0; i < ventilationData.length; i++) {
			data[p] = VENT.concat(" ").
					concat(Integer.toString(i + 1)).concat(" ").
					concat(Integer.toString(ventilationData[i][0])).concat(" ").
					concat(Integer.toString(ventilationData[i][1]));
			p++;
		}
		// ventilation auto config
		if(autoVentilation) {
			data[p] = VENT.concat(" ").
					concat("100 ").
					concat(Integer.toString(getMinTemp())).concat(" ").
					concat(Integer.toString(getMaxTemp()));
			p++;
			data[p] = VENT.concat(" ").
					concat("101 ").
					concat(Integer.toString(getMinHum())).concat(" ").
					concat(Integer.toString(getMaxHum()));
			p++;
		}
		// add watering times 
		for(int i = 0; i < wateringData.length; i++) {
			data[p] = WAT.concat(" ").
					concat(Integer.toString(i + 1)).concat(" ").
					concat(Integer.toString(wateringData[i][0])).concat(" ").
					concat(Integer.toString(wateringData[i][1]));
			p++;
		}
		// watering auto config
		if(autoWatering) {
			data[p] = WAT.concat(" ").
					concat("100 ").
					concat(Integer.toString(getMinSM())).concat(" ").
					concat(Integer.toString(getMaxSM()));
			p++;
		}
		// add delay data
		data[p] = "D 1 ".concat(Integer.toString(getRecDelay()));
		p++;
		data[p] = "D 2 ".concat(Integer.toString(getManDelay()));
		return data;
	}

	/*
	 * TimeList methods
	 */
	public int[][] parseTimesFromList(String[] list, int delayStep) {
		int[][] times = new int[list.length][2];
		for(int i = 0; i < list.length; i++) {
			String time = list[i].split(",")[0];
			times[i][0] = ((Integer.parseInt(time.split(":")[1]) / 10) + 
					(Integer.parseInt(time.split(":")[0]) * 6));

			String delay = list[i].split(",")[1];
			delay = delay.trim();
			delay = delay.split(" ")[0];
			times[i][1] = ((Integer.parseInt(delay) / delayStep));
		}
		return times;
	}

	public String[] createTimesList(int[][] times, String delayUnit, int delayStep) {
		if(times == null)
			return null;

		String[] list = new String[times.length];
		String time;
		String delay;
		for(int i = 0; i < list.length; i++) {
			time = ((times[i][0] / 6) < 10 
					? "0".concat(Integer.toString(times[i][0] / 6)) 
							: Integer.toString(times[i][0] / 6)).
							concat(":").concat(((times[i][0] * 10) % 60) < 10 
									? "0".concat(Integer.toString((times[i][0] * 10) % 60))
											: Integer.toString((times[i][0] * 10) % 60));
			delay = Integer.toString(times[i][1] * delayStep).concat(" ").concat(delayUnit);
			list[i] = time.concat(", ").concat(delay);
		}
		return list;
	}

	public String[] getWateringTimes() {
		return createTimesList(wateringData, WAT_DELAY_UNITS, WAT_DELAY_STEP);
	}

	public String[] getVentilationTimes() {
		return createTimesList(ventilationData, VENT_DELAY_UNITS, VENT_DELAY_STEP);
	}


	/*
	 * Encapsulation
	 */
	public boolean isRemoteAccess() {
		return remoteAccess;
	}

	public void setRemoteAccess(boolean remoteAccess) {
		this.remoteAccess = remoteAccess;
	}

	public int[][] getVentilationData() {
		return ventilationData;
	}

	public void setVentilationData(int[][] ventilationData) {
		this.ventilationData = ventilationData;
	}

	public int[][] getWateringData() {
		return wateringData;
	}

	public void setWateringData(int[][] wateringData) {
		this.wateringData = wateringData;
	}

	public int getRecDelay() {
		return recDelay;
	}

	public void setRecDelay(int recDelay) {
		this.recDelay = recDelay;
	}

	public int getManDelay() {
		return manDelay;
	}

	public void setManDelay(int manDelay) {
		this.manDelay = manDelay;
	}

	public boolean isAutoVentilation() {
		return autoVentilation;
	}

	public void setAutoVentilation(boolean autoVentilation) {
		this.autoVentilation = autoVentilation;
	}

	public boolean isAutoWatering() {
		return autoWatering;
	}

	public void setAutoWatering(boolean autoWatering) {
		this.autoWatering = autoWatering;
	}

	public int getMinTemp() {
		return minTemp;
	}

	public void setMinTemp(int minTemp) {
		this.minTemp = minTemp;
	}

	public int getMaxTemp() {
		return maxTemp;
	}

	public void setMaxTemp(int maxTemp) {
		this.maxTemp = maxTemp;
	}

	public int getMinHum() {
		return minHum;
	}

	public void setMinHum(int minHum) {
		this.minHum = minHum;
	}

	public int getMaxHum() {
		return maxHum;
	}

	public void setMaxHum(int maxHum) {
		this.maxHum = maxHum;
	}

	public int getMinSM() {
		return minSM;
	}

	public void setMinSM(int minSM) {
		this.minSM = minSM;
	}

	public int getMaxSM() {
		return maxSM;
	}

	public void setMaxSM(int maxSM) {
		this.maxSM = maxSM;
	}

	public String getUnitId() {
		return unitId;
	}

	public void setUnitId(String unitId) {
		this.unitId = unitId;
	}

}
